import time
import logging
from functools import wraps
from django.db import connection
from django.conf import settings
from django.core.cache import cache
import psutil
import json

logger = logging.getLogger(__name__)


class PerformanceMonitor:
    """性能监控器"""
    
    @staticmethod
    def monitor_api_performance(func):
        """API性能监控装饰器"""
        @wraps(func)
        def wrapper(*args, **kwargs):
            start_time = time.time()
            start_queries = len(connection.queries)
            
            try:
                result = func(*args, **kwargs)
                status = 'success'
            except Exception as e:
                result = None
                status = 'error'
                logger.error(f"API错误: {func.__name__} - {str(e)}")
                raise
            finally:
                end_time = time.time()
                end_queries = len(connection.queries)
                
                execution_time = end_time - start_time
                query_count = end_queries - start_queries
                
                # 记录性能数据
                performance_data = {
                    'function': func.__name__,
                    'execution_time': execution_time,
                    'query_count': query_count,
                    'status': status,
                    'timestamp': time.time()
                }
                
                # 如果执行时间超过阈值，记录警告
                if execution_time > 1.0:  # 1秒
                    logger.warning(f"慢查询警告: {func.__name__} 执行时间: {execution_time:.2f}s, 查询次数: {query_count}")
                
                # 将性能数据存储到缓存中（用于监控面板）
                cache_key = f"performance_monitor:{func.__name__}:{int(time.time())}"
                cache.set(cache_key, performance_data, 3600)  # 保存1小时
                
                logger.info(f"API性能: {func.__name__} - 时间: {execution_time:.2f}s, 查询: {query_count}")
            
            return result
        return wrapper
    
    @staticmethod
    def get_system_metrics():
        """获取系统指标"""
        try:
            cpu_percent = psutil.cpu_percent(interval=1)
            memory = psutil.virtual_memory()
            disk = psutil.disk_usage('/')
            
            return {
                'cpu_percent': cpu_percent,
                'memory_percent': memory.percent,
                'memory_used': memory.used,
                'memory_total': memory.total,
                'disk_percent': disk.percent,
                'disk_used': disk.used,
                'disk_total': disk.total,
                'timestamp': time.time()
            }
        except Exception as e:
            logger.error(f"获取系统指标失败: {str(e)}")
            return None
    
    @staticmethod
    def get_database_metrics():
        """获取数据库指标"""
        try:
            from django.db import connections
            
            metrics = {}
            for alias in connections:
                conn = connections[alias]
                with conn.cursor() as cursor:
                    # SQLite特定查询
                    if 'sqlite' in conn.settings_dict['ENGINE']:
                        cursor.execute("PRAGMA database_list")
                        db_info = cursor.fetchall()
                        
                        cursor.execute("SELECT COUNT(*) FROM sqlite_master WHERE type='table'")
                        table_count = cursor.fetchone()[0]
                        
                        metrics[alias] = {
                            'database_info': db_info,
                            'table_count': table_count,
                            'connection_queries': len(connection.queries)
                        }
            
            return metrics
        except Exception as e:
            logger.error(f"获取数据库指标失败: {str(e)}")
            return None
    
    @staticmethod
    def get_cache_metrics():
        """获取缓存指标"""
        try:
            # 这里需要根据实际使用的缓存后端来实现
            # Redis示例
            cache_stats = {
                'hits': 0,
                'misses': 0,
                'keys': 0
            }
            
            # 如果使用Redis，可以通过redis客户端获取统计信息
            try:
                from django_redis import get_redis_connection
                redis_conn = get_redis_connection("default")
                info = redis_conn.info()
                
                cache_stats = {
                    'hits': info.get('keyspace_hits', 0),
                    'misses': info.get('keyspace_misses', 0),
                    'keys': info.get('db0', {}).get('keys', 0) if 'db0' in info else 0,
                    'memory_usage': info.get('used_memory', 0),
                    'connected_clients': info.get('connected_clients', 0)
                }
            except ImportError:
                pass
            
            return cache_stats
        except Exception as e:
            logger.error(f"获取缓存指标失败: {str(e)}")
            return None


class RequestLoggingMiddleware:
    """请求日志中间件"""
    
    def __init__(self, get_response):
        self.get_response = get_response
    
    def __call__(self, request):
        start_time = time.time()
        
        # 记录请求信息
        request_data = {
            'method': request.method,
            'path': request.path,
            'user': str(request.user) if hasattr(request, 'user') and request.user.is_authenticated else 'Anonymous',
            'ip': self.get_client_ip(request),
            'user_agent': request.META.get('HTTP_USER_AGENT', ''),
            'timestamp': start_time
        }
        
        response = self.get_response(request)
        
        end_time = time.time()
        execution_time = end_time - start_time
        
        # 记录响应信息
        response_data = {
            **request_data,
            'status_code': response.status_code,
            'execution_time': execution_time,
            'response_size': len(response.content) if hasattr(response, 'content') else 0
        }
        
        # 记录到日志
        log_level = logging.INFO
        if response.status_code >= 400:
            log_level = logging.WARNING
        if response.status_code >= 500:
            log_level = logging.ERROR
        
        logger.log(log_level, f"请求日志: {json.dumps(response_data, ensure_ascii=False)}")
        
        # 如果是慢请求，额外记录
        if execution_time > 2.0:  # 2秒
            logger.warning(f"慢请求: {request.method} {request.path} - {execution_time:.2f}s")
        
        return response
    
    def get_client_ip(self, request):
        """获取客户端IP"""
        x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
        if x_forwarded_for:
            ip = x_forwarded_for.split(',')[0]
        else:
            ip = request.META.get('REMOTE_ADDR')
        return ip


def health_check():
    """健康检查函数"""
    health_status = {
        'status': 'healthy',
        'timestamp': time.time(),
        'checks': {}
    }
    
    # 检查数据库连接
    try:
        from django.db import connection
        with connection.cursor() as cursor:
            cursor.execute("SELECT 1")
        health_status['checks']['database'] = 'healthy'
    except Exception as e:
        health_status['checks']['database'] = f'unhealthy: {str(e)}'
        health_status['status'] = 'unhealthy'
    
    # 检查缓存连接
    try:
        cache.set('health_check', 'ok', 10)
        cache.get('health_check')
        health_status['checks']['cache'] = 'healthy'
    except Exception as e:
        health_status['checks']['cache'] = f'unhealthy: {str(e)}'
        health_status['status'] = 'unhealthy'
    
    # 检查系统资源
    try:
        metrics = PerformanceMonitor.get_system_metrics()
        if metrics:
            if metrics['cpu_percent'] > 90:
                health_status['checks']['cpu'] = f'warning: {metrics["cpu_percent"]}%'
            else:
                health_status['checks']['cpu'] = 'healthy'
            
            if metrics['memory_percent'] > 90:
                health_status['checks']['memory'] = f'warning: {metrics["memory_percent"]}%'
            else:
                health_status['checks']['memory'] = 'healthy'
        else:
            health_status['checks']['system'] = 'unable to check'
    except Exception as e:
        health_status['checks']['system'] = f'error: {str(e)}'
    
    return health_status
